package com.chang.springsecurity.security.filter;

import com.chang.springsecurity.security.service.UserDetailsServiceImpl;
import com.chang.springsecurity.security.util.JwtUtil;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private final JwtUtil jwtUtil;

    private final UserDetailsServiceImpl userDetailsService;

    public JwtAuthenticationFilter(JwtUtil jwtUtil, UserDetailsServiceImpl userDetailsService) {
        this.jwtUtil = jwtUtil;
        this.userDetailsService = userDetailsService;
    }

    @Override
    public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = extractTokenFromHeader(request);

        if(token != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            // 1. 验证Token是否有效（签名+过期）
            if(jwtUtil.validateToken(token)) {
                // 2. 获取Token中的用户名
                String username = jwtUtil.getUsernameFromToken(token);

                // 3. 根据用户名获取用户信息
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);

                // 4. 构造已认证的Authentication对象
                UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

                // 5. 将已认证的Authentication对象设置到SecurityContextHolder中(ThreadLocal)
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }
            // 6. Token无效，不设置认证，后续由EntryPoint返回401，放行
        }
        // 7. 继续执行后续过滤器
        filterChain.doFilter(request, response);
    }

    /*
    * 从Authorization Header 中提取 Bearer Token
    * 格式：Authorization: Bearer <token>
    * */
    private String extractTokenFromHeader(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}
